package com.zjw.service.impl;

import com.zjw.constants.SystemConstants;
import com.zjw.annotation.domain.ResponseResult;
import com.zjw.annotation.domain.entity.User;
import com.zjw.annotation.domain.vo.BlogUserLoginVo;
import com.zjw.annotation.domain.vo.UserInfoVo;
import com.zjw.enums.AppHttpCodeEnum;
import com.zjw.service.BlogLoginService;
import com.zjw.utils.BeanCopyUtils;
import com.zjw.utils.JwtUtil;
import com.zjw.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

@Service
public class BlogLoginServiceImpl implements BlogLoginService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisCache redisCache;

    @Override
    public ResponseResult login(User user) {
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());

        Authentication authenticate = authenticationManager.authenticate(authenticationToken);

//        在authenticate方法中会对输入的用户名密码和数据库中查询返回的LoginUser进行匹配，如果不匹配返回Null
        if (authenticate == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_ERROR);
        }

//        如果运行到此处，证明登录认证的步骤都完全正确

//        获取出已授权对象中的主体对象
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        User targetUser = loginUser.getUser();

//        1. 根据用户id生成jwt
        String jwt = JwtUtil.createJWT(targetUser.getId().toString());

//        2. 将jwt存入Redis; key: blogLogin:<用户id> ; value: User
        redisCache.setCacheObject(SystemConstants.JWT_KEY_PREFIX + targetUser.getId().toString(), targetUser);

//        3. 将数据封装返回给前端
        BlogUserLoginVo res = new BlogUserLoginVo(BeanCopyUtils.copy(targetUser, UserInfoVo.class), jwt);

        return ResponseResult.okResult(res);
    }

    @Override
    public ResponseResult logout() {

//       因为请求进来都会通过自定义的jwt过滤器过滤
//       所以在这里直接获取到当前登录用户
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser principal = (LoginUser) authentication.getPrincipal();
//        登录主体是UserDetails的实现类

//        获取到用户对象
        User curUser = principal.getUser();

//        获取到key从Redis中移除对应键值对
        String key = SystemConstants.JWT_KEY_PREFIX + curUser.getId().toString();
//        移除
        redisCache.deleteObject(key);

        return ResponseResult.okResult();
    }
}
